package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.content.model.dto.TeachplanDTO;
import com.xuecheng.api.content.model.dto.TeachplanMediaDTO;
import com.xuecheng.api.media.model.dto.MediaDTO;
import com.xuecheng.api.teaching.model.dto.TeachplanWorkDTO;
import com.xuecheng.api.teaching.model.dto.WorkDTO;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.AuditEnum;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.common.ResourceTypeEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseModeEnum;
import com.xuecheng.common.enums.content.TeachPlanEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.agent.MediaApiAgent;
import com.xuecheng.content.agent.TeachingApiAgent;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.convert.TeachplanConvert;
import com.xuecheng.content.convert.TeachplanMediaConvert;
import com.xuecheng.content.convert.TeachplanWorkConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.Teachplan;
import com.xuecheng.content.entity.TeachplanMedia;
import com.xuecheng.content.entity.TeachplanWork;
import com.xuecheng.content.entity.ext.TeachplanNode;
import com.xuecheng.content.mapper.TeachplanMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.TeachplanMediaService;
import com.xuecheng.content.service.TeachplanService;
import com.xuecheng.content.service.TeachplanWorkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 课程计划 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class TeachplanServiceImpl extends ServiceImpl<TeachplanMapper, Teachplan> implements TeachplanService {

    @Autowired
    private CourseBaseService courseBaseService;


    @Autowired
    private RedisTemplate<String, Serializable> serializableRedisTemplate;


    @Autowired
    private TeachplanMediaService teachplanMediaService;

    @Autowired
    private TeachplanWorkService teachplanWorkService;


    @Autowired
    private MediaApiAgent mediaApiAgent;

    @Autowired
    private TeachingApiAgent teachingApiAgent;

    /*
    * 业务分析：
    *   1.判断关键数据
    *       courseId companyId
    *   2.判断业务数据
    *       课程基础信息
    *           判断是否存在
    *           判断是否是同一家教学机构
    *           判断是否删除
    *   3.根据Courseid查询课程计划数据
    *   4.通过java的递归生成课程计划树形结构
    *   5.将数据转为dto并返回
    * */
    public TeachplanDTO getTreeNodes(Long courseId, Long companyId) {

        // 1.判断关键数据
        //      courseId companyId
        if (ObjectUtils.isEmpty(courseId)||
                ObjectUtils.isEmpty(companyId)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        //  2.判断业务数据
        //      课程基础信息
        //          判断是否存在
        //          判断是否是同一家教学机构
        //          判断是否删除
        LambdaQueryWrapper<CourseBase> baseQueryWrapper = new LambdaQueryWrapper<>();
        baseQueryWrapper.eq(CourseBase::getId, courseId);
        baseQueryWrapper.eq(CourseBase::getCompanyId, companyId);

        CourseBase courseBase = courseBaseService.getOne(baseQueryWrapper);

        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }

        Integer status = courseBase.getStatus();
        if (!(CommonEnum.USING_FLAG.getCodeInt().equals(status))) {
            ExceptionCast.cast(ContentErrorCode.E_120021);
        }

        //  3.根据Courseid查询课程计划数据
        TeachplanMapper baseMapper = this.getBaseMapper();
        List<TeachplanNode> nodes = baseMapper.selectTreeNodesByCourseId(courseId);


        //  4.通过java的递归生成课程计划树形结构

        TeachplanDTO teachplanDTO = null;
        if (CollectionUtils.isEmpty(nodes)) {
            teachplanDTO = new TeachplanDTO();
        } else {

            TeachplanNode rootNode = nodes.remove(0);

            generateTreeNodes(rootNode,nodes);

            teachplanDTO = TeachplanConvert.INSTANCE.node2dto(rootNode);
        }


        //  5.将数据转为dto并返回
        return teachplanDTO;
    }



    private void generateTreeNodes(TeachplanNode parentNode, List<TeachplanNode> nodes) {

        // 1.判断父级集合是否为空，如果为空需要创建
        if (CollectionUtils.isEmpty(parentNode.getChildrenNodes())) {
            parentNode.setChildrenNodes(new ArrayList<>(8));
        }

        // 2.循环遍历集合生成树形结构
        for (TeachplanNode node : nodes) {

            // 2.1 判断node是否和parentnode有关联，如果有关联将node存放到parentNode集合中
            if (ObjectUtils.nullSafeEquals(parentNode.getId(),node.getParentid())) {

                parentNode.getChildrenNodes().add(node);

                // 2.2 生成node集合数据
                // 如果是第三级课程计划，无需递归
                if (!(TeachPlanEnum.THIRD_LEVEL.equals(node.getGrade()))) {
                    generateTreeNodes(node, nodes);
                } else {
                    // 如果是第三级课程计划，需要查询是否有关联的媒资信息
                    LambdaQueryWrapper<TeachplanMedia> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(TeachplanMedia::getTeachplanId, node.getId());
                    queryWrapper.eq(TeachplanMedia::getCourseId, node.getCourseId());

                    TeachplanMedia teachplanMedia = teachplanMediaService.getOne(queryWrapper);

                    LambdaQueryWrapper<TeachplanWork> workQueryWrapper = new LambdaQueryWrapper<>();
                    workQueryWrapper.eq(TeachplanWork::getTeachplanId,node.getId());
                    workQueryWrapper.eq(TeachplanWork::getCourseId,node.getCourseId());
                    TeachplanWork teachplanWork = teachplanWorkService.getOne(workQueryWrapper);

                    if (!(ObjectUtils.isEmpty(teachplanMedia))) {
                        node.setTeachplanMedia(teachplanMedia);
                    }
                    if (!(ObjectUtils.isEmpty(teachplanWork))) {
                        node.setWork(teachplanWork);
                    }
                }
            }
        }

    }


    /*
    * 业务分析：
    *   主体方法
    *       1.判断业务操作
    *           判断是创建还是修改：teachplanId
    *           如果有:修改
    *           如果没有:创建
    *
    *       2.执行创建和修改操作并返回dto数据
    *
    *       3.返回结果数据dto
    * */
    @Transactional
    public TeachplanDTO createOrModifyTeachplan(TeachplanDTO dto, Long companyId) {

        TeachplanDTO resutlDTO = null;
        //1.判断业务操作
        //     判断是创建还是修改：teachplanId
        //     如果有:修改
        //     如果没有:创建
        // 2.执行创建和修改操作并返回dto数据
        if (ObjectUtils.isEmpty(dto.getTeachPlanId())) {
            resutlDTO = createTeachplan(dto, companyId);
        } else {
            resutlDTO = modifyTeachplan(dto, companyId);
        }

        // 3.返回结果数据dto
        return resutlDTO;
    }




    /*
    * 业务分析：
    *    1.判断关键数据
         2.判断业务数据
             课程基础信息
                 判断是否存在
                 判断是否同一家机构
                 判断是否删除
                 判断课程基础信息审核状态：未提交和审核未通过
             课程计划
                 判断是否存在
         3.修改课程计划数据
              pname starttime endtime is_preview
         4.判断修改后的结果
         5.将数据库最新的数据转为dto并返回
    * */
    private TeachplanDTO modifyTeachplan(TeachplanDTO dto, Long companyId) {

        // 1.判断关键数据
        // 2.判断业务数据
        //      课程基础信息
        //          判断是否存在
        //          判断是否同一家机构
        //          判断是否删除
        //          判断课程基础信息审核状态：未提交和审核未通过
        CourseBaseDTO baseDTO = verifyTeachplanMsg(dto, companyId);


        //      课程计划
        //          判断是否存在
        LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teachplan::getId, dto.getTeachPlanId());
        int count = this.count(queryWrapper);
        if (count < 1) {
            ExceptionCast.cast(ContentErrorCode.E_120402);
        }


        //  3.修改课程计划数据
        //       pname starttime endtime is_preview
        LambdaUpdateWrapper<Teachplan> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Teachplan::getPname, dto.getPname());
        updateWrapper.set(Teachplan::getStartTime, dto.getStartTime());
        updateWrapper.set(Teachplan::getEndTime, dto.getEndTime());
        updateWrapper.set(Teachplan::getIsPreview, dto.getIsPreview());

        updateWrapper.eq(Teachplan::getId, dto.getTeachPlanId());


        //  4.判断修改后的结果
        boolean result = this.update(updateWrapper);

        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120407);
        }

        //  5.将数据库最新的数据转为dto并返回
        Teachplan po = this.getById(dto.getTeachPlanId());

        TeachplanDTO resultDTO = TeachplanConvert.INSTANCE.entity2dto(po);

        return resultDTO;
    }

    /*
    * 主体方法业务分析：
    *   1.判断关键数据
    *   2.判断业务数据
    *       课程基础信息
    *           判断是否存在
    *           判断是否同一家机构
    *           判断是否删除
    *           判断课程基础信息审核状态：未提交和审核未通过
    *   3.获得父级数据并进行关联
    *       parentid
    *       grade：子级grade是父级grade+1
    *       orderby：获得父级课程计划的子级数据个数+1（bug）
    *   4.将dto转为po并保存
    *   5.判断保存后的结果
    *   6.将数据库最新数据转为dto并返回
    *
    * */
    private TeachplanDTO createTeachplan(TeachplanDTO dto, Long companyId) {

        CourseBaseDTO courseBase = verifyTeachplanMsg(dto, companyId);


        // 3.获得父级数据并进行关联
        //     parentid
        //     grade：子级grade是父级grade+1
        //     orderby：获得父级课程计划的子级数据个数+1（bug）
        Teachplan teachplan = TeachplanConvert.INSTANCE.dto2entity(dto);

        Teachplan parentNode =  generateParentNode(dto,courseBase);

        teachplan.setParentid(parentNode.getId());
        teachplan.setGrade(parentNode.getGrade()+1);

        // 源数据库的代码-存在问题
        // select count(1) from teachplan where parentId = parentNode.getId();
        // LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
        // queryWrapper.eq(Teachplan::getParentid, parentNode.getId());
        //
        // int count = this.count(queryWrapper);
        // teachplan.setOrderby(count+1);

        // 使用redis方案来解决
        HashOperations<String, Object, Object> hashOps = serializableRedisTemplate.opsForHash();

        String hashKey = parentNode.getId() + ":" + parentNode.getGrade();
        Long countNum = hashOps.increment(courseBase.getCourseBaseId().toString(),
                hashKey,
                1);
        teachplan.setOrderby(countNum.intValue());



        // 4.将dto转为po并保存
        boolean result = this.save(teachplan);

        // 5.判断保存后的结果
        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120407);
        }


        // 6.将数据库最新数据转为dto并返回
        Teachplan po = this.getById(teachplan.getId());

        TeachplanDTO resultDTO = TeachplanConvert.INSTANCE.entity2dto(po);

        return resultDTO;
    }

    private CourseBaseDTO verifyTeachplanMsg(TeachplanDTO dto, Long companyId) {
        //1.判断关键数据
        if (ObjectUtils.isEmpty(companyId)||
                StringUtil.isBlank(dto.getPname())||
                ObjectUtils.isEmpty(dto.getCourseId())
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }


        Long courseId = dto.getCourseId();
        // 2.判断业务数据
        return getCourseAndVerify(companyId, courseId);
    }

    private CourseBaseDTO getCourseAndVerify(Long companyId, Long courseId) {
        //     课程基础信息
        //         判断是否存在
        //         判断是否同一家机构
        //         判断是否删除
        //         判断课程基础信息审核状态：未提交和审核未通过
        CourseBaseDTO courseBase = courseBaseService.getCourseBaseById(courseId, companyId);

        String auditStatus = courseBase.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }
        return courseBase;
    }


    /*
    * 业务分析：
    *   1.判断新增数据是二级还是三级课程计划
    *       判断新增数据是否有parentId值
    *           如果有：三级课程计划
    *           如果没有：二级课程计划
    *   2.获得二级课程计划的父级数据
    *       查询数据库获得一级课程计划：courseId、parentid=0
    *           如果没有：自动创建并保存数据--数据来源 coursebase
    *           如果有：直接返回
    *   3.获得三级课程计划的父级数据
    *       查询数据库获得二级课程计划：parentId
    *           如果没有：直接抛出异常
    *           如果有：直接返回
    * */
    private Teachplan generateParentNode(TeachplanDTO dto, CourseBaseDTO courseBase) {

        //1.判断新增数据是二级还是三级课程计划
        //     判断新增数据是否有parentId值
        //         如果有：三级课程计划
        //         如果没有：二级课程计划
        Long parentid = dto.getParentid();
        if (ObjectUtils.isEmpty(parentid)) {
        // 2.获得二级课程计划的父级数据
        //     查询数据库获得一级课程计划：courseId、parentid=0
        //         如果没有：自动创建并保存数据--数据来源 coursebase
        //         如果有：直接返回
            LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Teachplan::getCourseId, courseBase.getCourseBaseId());
            queryWrapper.eq(Teachplan::getParentid, TeachPlanEnum.FIRST_PARENTID_FLAG);

            Teachplan rootParent = this.getOne(queryWrapper);

            if (ObjectUtils.isEmpty(rootParent)) {

                rootParent = new Teachplan();
                rootParent.setPname(courseBase.getName());
                rootParent.setParentid(new Long(TeachPlanEnum.FIRST_PARENTID_FLAG));
                rootParent.setGrade(TeachPlanEnum.FIRST_LEVEL);
                rootParent.setDescription(courseBase.getDescription());
                rootParent.setOrderby(TeachPlanEnum.FIRST_LEVEL);
                rootParent.setCourseId(courseBase.getCourseBaseId());
                boolean save = this.save(rootParent);

                if (!save) {
                    ExceptionCast.cast(ContentErrorCode.E_120415);
                }
            }

            return rootParent;

        } else {
        // 3.获得三级课程计划的父级数据
        //     查询数据库获得二级课程计划：parentId
        //         如果没有：直接抛出异常
        //         如果有：直接返回
            LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Teachplan::getId, parentid);

            Teachplan teachplan = this.getOne(queryWrapper);

            if (ObjectUtils.isEmpty(teachplan)) {
                ExceptionCast.cast(ContentErrorCode.E_120408);
            }

            return teachplan;
        }
    }



    @Override
    public void removeTeachPlan(Long teachPlanId, Long companyId) {

        //1.判断关键数据的合法性
        Teachplan teachplan = getById(teachPlanId);

        if (ObjectUtils.isEmpty(teachplan)) ExceptionCast.cast(ContentErrorCode.E_120402);

        // 2.判断业务数据
        CourseBaseDTO coursebase = getCourseAndVerify(companyId, teachplan.getCourseId());


        // 3. 根据课程计划等级进行业务判断
        if (teachplan.getGrade() == TeachPlanEnum.SECEND_LEVEL) {

            // 判断二级课程计划是否有子级课程计划信息
            LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Teachplan::getParentid, teachPlanId);
            int count = count(queryWrapper);


            if (count > 0)
                ExceptionCast.cast(ContentErrorCode.E_120409);


        } else {
            // 如果是录播课程需要判断是否有关联媒资信息
            // 判断三级课程计划是否关联课程媒资信息
            String teachmode = coursebase.getTeachmode();
            if (CourseModeEnum.COURSE_MODE_RECORD_STATUS.getCode().equals(teachmode)) {
                LambdaQueryWrapper<TeachplanMedia>
                        mediaLambdaQueryWrapper = new LambdaQueryWrapper<>();

                mediaLambdaQueryWrapper.eq(TeachplanMedia::getTeachplanId,teachPlanId);

                int mediaCount = teachplanMediaService.count(mediaLambdaQueryWrapper);

                if (mediaCount > 0) ExceptionCast.cast(ContentErrorCode.E_120413);
            }

        }
        // 4.根据Id删除课程计划
        removeById(teachPlanId);
    }


    /*
    * 业务分析：
    *   1.判断关键数据
    *       teachplanid mediaid
    *
    *   2.判断业务数据
    *       课程计划数据
    *           判断是否存在
    *           判断课程计划是否是第三级
    *           判断是否是同一家机构的操作
    *               根据课程基础信息来查询
    *               判断课程类型是否是点播
    *       媒资数据
    *           判断是否存在
    *           判断是否是同一家机构
    *           判断媒资信息是否审核通过
    *
    *   3.保存课程计划和媒资信息关联关系
    *       判断关联数据是否存在
    *           如果不存在
    *               创建数据
    *           如果存在
    *               修改数据
    *                   mediaid 和 medianame
    *
    *
    *   4.将数据封装成dto并返回
    * */
    @Transactional
    public TeachplanMediaDTO associationMedia(TeachplanMediaDTO dto,Long companyId) {

        // 1.判断关键数据
        //      teachplanid mediaid companyId
        if (ObjectUtils.isEmpty(dto.getTeachplanId())||
                ObjectUtils.isEmpty(dto.getMediaId())||
                ObjectUtils.isEmpty(companyId)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }


        //  2.判断业务数据
        //      课程计划数据
        //          判断是否存在
        //          判断课程计划是否是第三级
        LambdaQueryWrapper<Teachplan> teachplanQueryWrapper = new LambdaQueryWrapper<>();

        teachplanQueryWrapper.eq(Teachplan::getId, dto.getTeachplanId());
        teachplanQueryWrapper.eq(Teachplan::getGrade, TeachPlanEnum.THIRD_LEVEL);

        Teachplan teachplan = this.getOne(teachplanQueryWrapper);

        if (ObjectUtils.isEmpty(teachplan)) {
            ExceptionCast.cast(ContentErrorCode.E_120402);
        }


        //       课程基础信息
        //          判断是否是同一家机构的操作
        //              根据课程基础信息来查询
        //              判断课程类型是否是点播
        LambdaQueryWrapper<CourseBase> baseQueryWrapper = new LambdaQueryWrapper<>();

        baseQueryWrapper.eq(CourseBase::getId, teachplan.getCourseId());
        baseQueryWrapper.eq(CourseBase::getCompanyId, companyId);
        baseQueryWrapper.eq(CourseBase::getTeachmode, CourseModeEnum.COURSE_MODE_RECORD_STATUS.getCode());
        baseQueryWrapper.eq(CourseBase::getStatus, CommonEnum.USING_FLAG.getCodeInt());

        CourseBase courseBase = courseBaseService.getOne(baseQueryWrapper);

        // 课程计划和媒资信息绑定要求课程审核状态为：未提交和审核未通过
        String auditStatus = courseBase.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }


        //      媒资数据
        //          判断是否存在
        //          判断是否是同一家机构
        //          判断媒资信息是否审核通过
        RestResponse<MediaDTO> restResponse = mediaApiAgent.getMediaById4s(dto.getMediaId());

        if (!(restResponse.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(restResponse.getCode(),restResponse.getMsg());
        }

        MediaDTO mediaDTO = restResponse.getResult();

        if (!(ObjectUtils.nullSafeEquals(mediaDTO.getCompanyId(),companyId))) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }

        String mediaAuditStatus = mediaDTO.getAuditStatus();

        if (!(AuditEnum.AUDIT_PASTED_STATUS.getCode().equals(mediaAuditStatus))) {
            ExceptionCast.cast(ContentErrorCode.E_120416);
        }


        //  3.保存课程计划和媒资信息关联关系
        //      判断关联数据是否存在
        LambdaQueryWrapper<TeachplanMedia> teachplanMediaQueryWrapper = new LambdaQueryWrapper<>();
        teachplanMediaQueryWrapper.eq(TeachplanMedia::getTeachplanId,teachplan.getId());
        teachplanMediaQueryWrapper.eq(TeachplanMedia::getCourseId,teachplan.getCourseId());

        int count = teachplanMediaService.count(teachplanMediaQueryWrapper);

        boolean result = false;
        if (count < 1) {
        //          如果不存在
        //              创建数据
            TeachplanMedia teachplanMedia = new TeachplanMedia();
            teachplanMedia.setMediaId(mediaDTO.getId());
            teachplanMedia.setTeachplanId(teachplan.getId());
            teachplanMedia.setCourseId(teachplan.getCourseId());
            teachplanMedia.setMediaFilename(mediaDTO.getFilename());
            //视频类型
            LambdaUpdateWrapper<Teachplan> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Teachplan::getId,dto.getTeachplanId());
            updateWrapper.set(Teachplan::getMediaType,ResourceTypeEnum.VIDEO.getCode());
            this.update(updateWrapper);

            result = teachplanMediaService.save(teachplanMedia);


        } else {
        //          如果存在
        //              修改数据
        //                  mediaid 和 medianame
            LambdaUpdateWrapper<TeachplanMedia> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(TeachplanMedia::getMediaId, mediaDTO.getId());
            updateWrapper.set(TeachplanMedia::getMediaFilename, mediaDTO.getFilename());
            updateWrapper.eq(TeachplanMedia::getTeachplanId, teachplan.getId());
            //视频类型
            LambdaUpdateWrapper<Teachplan> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(Teachplan::getId,dto.getTeachplanId());
            wrapper.set(Teachplan::getMediaType,ResourceTypeEnum.VIDEO.getCode());
            this.update(wrapper);

            result = teachplanMediaService.update(updateWrapper);
        }

        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120411);
        }



        //  4.将数据封装成dto并返回
        LambdaQueryWrapper<TeachplanMedia> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TeachplanMedia::getTeachplanId, teachplan.getId());

        TeachplanMedia teachplanMedia = teachplanMediaService.getOne(queryWrapper);

        TeachplanMediaDTO resultDTO = TeachplanMediaConvert.INSTANCE.entity2dto(teachplanMedia);


        return resultDTO;
    }

    /**
     * 课程计划和作业信息绑定
     * @param dto
     * @param companyId
     * @return
     */
    @Override
    @Transactional
    public TeachplanWorkDTO associateWork(TeachplanWorkDTO dto, Long companyId) {
        Long teachplanId = dto.getTeachplanId();
        String workTitle = dto.getWorkTitle();
        // 1.判断关键数据
        if (ObjectUtils.isEmpty(teachplanId)||
                ObjectUtils.isEmpty(dto.getWorkId())||
                ObjectUtils.isEmpty(workTitle)||
                ObjectUtils.isEmpty(companyId)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //2.判断业务数据
        //2.1课程计划数据
        //判断是否存在，等级是否为第3级
        LambdaQueryWrapper<Teachplan> teachplanQueryWrapper = new LambdaQueryWrapper<>();
        teachplanQueryWrapper.eq(Teachplan::getId,teachplanId);
        teachplanQueryWrapper.eq(Teachplan::getGrade,TeachPlanEnum.THIRD_LEVEL);
        Teachplan teachplan = this.getOne(teachplanQueryWrapper);
        if (ObjectUtils.isEmpty(teachplan)) {
            ExceptionCast.cast(ContentErrorCode.E_120402);
        }
        //2.2课程基础信息
        Long courseId = teachplan.getCourseId();
        LambdaQueryWrapper<CourseBase> courseQueryWrapper = new LambdaQueryWrapper<>();
        courseQueryWrapper.eq(CourseBase::getCompanyId,companyId);
        courseQueryWrapper.eq(CourseBase::getStatus,CommonEnum.USING_FLAG.getCodeInt());
        courseQueryWrapper.eq(CourseBase::getId, courseId);
        CourseBase courseBase = courseBaseService.getOne(courseQueryWrapper);
        //课程审核状态判断
        String auditStatus = courseBase.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }
        //2.3作业数据判断
        Long workId = dto.getWorkId();
        RestResponse<WorkDTO> response = teachingApiAgent.getWorkById4c(workId);
        if (!(response.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(response.getCode(),response.getMsg());
        }
        WorkDTO resultWorkDTO = response.getResult();
        //判断是否同一家机构
        if (!(resultWorkDTO.getCompanyId().equals(companyId))) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
        Integer status = resultWorkDTO.getStatus();
        if (!(CommonEnum.USING_FLAG.getCodeInt().equals(status))) {
            ExceptionCast.cast(ContentErrorCode.E_120417);
        }
        //3.关联课程计划和作业信息
        LambdaQueryWrapper<TeachplanWork> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TeachplanWork::getTeachplanId,teachplanId);
        wrapper.eq(TeachplanWork::getCourseId,courseId);
        int count = teachplanWorkService.count(wrapper);

        Boolean result = false;
        if (count < 1) {
            //不存在关联数据，创建数据
            TeachplanWork teachplanWork = new TeachplanWork();
            teachplanWork.setCourseId(courseId);
            teachplanWork.setWorkId(workId);
            teachplanWork.setTeachplanId(teachplanId);
            teachplanWork.setWorkTitle(workTitle);
            //作业类型
            LambdaUpdateWrapper<Teachplan> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Teachplan::getId,teachplanId);
            updateWrapper.set(Teachplan::getMediaType,ResourceTypeEnum.WORK.getCode());
            this.update(updateWrapper);

            result = teachplanWorkService.save(teachplanWork);
        } else {
            //存在关联数据，修改数据
            LambdaUpdateWrapper<TeachplanWork> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(TeachplanWork::getWorkId, workId);
            updateWrapper.set(TeachplanWork::getWorkTitle, workTitle);
            updateWrapper.eq(TeachplanWork::getTeachplanId, teachplanId);
            //作业类型
            LambdaUpdateWrapper<Teachplan> updatePlanWrapper = new LambdaUpdateWrapper<>();
            updatePlanWrapper.set(Teachplan::getMediaType,ResourceTypeEnum.WORK.getCode());
            updatePlanWrapper.eq(Teachplan::getId,teachplanId);
            this.update(updatePlanWrapper);

            result = teachplanWorkService.update(updateWrapper);
        }
        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120418);
        }
        //4.将数据封装成dto并返回
        LambdaQueryWrapper<TeachplanWork> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TeachplanWork::getTeachplanId, teachplan.getId());
        TeachplanWork teachplanWork = teachplanWorkService.getOne(queryWrapper);
        TeachplanWorkDTO resultDTO = TeachplanWorkConvert.INSTANCE.entity2dto(teachplanWork);

        return resultDTO;
    }


    /**
     * 课程计划和作业信息解绑
     * @param teachplanWorkId
     * @param courseBaseId
     * @param companyId
     */
    @Override
    @Transactional
    public void deleteTeachplanWork(String teachplanWorkId,Long courseBaseId, Long companyId) {
        //关键数据判断
        if (ObjectUtils.isEmpty(teachplanWorkId)
                ||ObjectUtils.isEmpty(companyId)
                ||ObjectUtils.isEmpty(courseBaseId)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //业务数据判断
        //课程基本信息
        courseBaseService.getCourseBaseById(courseBaseId, companyId);
        //作业计划信息
        LambdaQueryWrapper<TeachplanWork> workWrapper = new LambdaQueryWrapper<>();
        workWrapper.eq(TeachplanWork::getTeachplanWorkId,teachplanWorkId);
        workWrapper.eq(TeachplanWork::getCourseId,courseBaseId);
        TeachplanWork teachplanWork = teachplanWorkService.getOne(workWrapper);
        if (ObjectUtils.isEmpty(teachplanWork)) {
            ExceptionCast.cast(ContentErrorCode.E_120417);
        }
        //课程计划
        LambdaQueryWrapper<Teachplan> teachplanQueryWrapper = new LambdaQueryWrapper<>();
        teachplanQueryWrapper.eq(Teachplan::getCourseId,courseBaseId);
        teachplanQueryWrapper.eq(Teachplan::getGrade,TeachPlanEnum.THIRD_LEVEL);
        teachplanQueryWrapper.eq(Teachplan::getId,teachplanWork.getTeachplanId());
        Teachplan teachplan = this.getOne(teachplanQueryWrapper);
        if (ObjectUtils.isEmpty(teachplan)) {
            ExceptionCast.cast(ContentErrorCode.E_120402);
        }
        //删除作业绑定信息
        LambdaUpdateWrapper<TeachplanWork> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(TeachplanWork::getTeachplanWorkId,teachplanWorkId);
        wrapper.eq(TeachplanWork::getCourseId,courseBaseId);
        boolean result = teachplanWorkService.remove(wrapper);
        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120419);
        }
    }
}
